package com.ebt.m.cloud.db;

import com.ebt.m.cloud.bean.MyBusinessInfLocal;
import com.ebt.m.cloud.bean.MyDownloadInfLocal;
import com.ebt.m.cloud.bean.MyDownloadThreadInfoLocal;
import com.ebt.m.cloud.downloader.db.DownloadDBController;
import com.ebt.m.cloud.downloader.domain.DownloadInfo;
import com.ebt.m.cloud.downloader.domain.DownloadThreadInfo;
import com.ebt.m.data.greendao.GreenDaoManager;
import com.ebt.m.data.greendao.MyBusinessInfLocalDao;
import com.ebt.m.data.greendao.MyDownloadInfLocalDao;
import com.ebt.m.data.greendao.MyDownloadThreadInfoLocalDao;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;


/**
 *
 * @author Damon.Han
 */

public class DBController implements DownloadDBController {

    private static DBController instance;
    private final MyBusinessInfLocalDao myBusinessInfoLocalsDao;
    private final MyDownloadInfLocalDao myDownloadInfLocalDao;
    private final MyDownloadThreadInfoLocalDao myDownloadThreadInfoLocalDao;

    public DBController() {
        try {
            myBusinessInfoLocalsDao = GreenDaoManager.getInstance().getSession().getMyBusinessInfLocalDao();
            myDownloadInfLocalDao = GreenDaoManager.getInstance().getSession().getMyDownloadInfLocalDao();
            myDownloadThreadInfoLocalDao = GreenDaoManager.getInstance().getSession().getMyDownloadThreadInfoLocalDao();
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    public static DBController getInstance() throws SQLException {
        if (instance == null) {
            instance = new DBController();
        }
        return instance;
    }


    public void createOrUpdateMyDownloadInfo(MyBusinessInfLocal downloadInfoLocal)
            throws SQLException {
        myBusinessInfoLocalsDao.insertOrReplace(downloadInfoLocal);
    }

    public void deleteMyDownloadInfo(long id) {
        myBusinessInfoLocalsDao.deleteByKey(id);
    }

    public MyBusinessInfLocal findMyDownloadInfoById(long id)
            throws SQLException {
        return myBusinessInfoLocalsDao.load(id);
    }

    @Override
    public List<DownloadInfo> findAllDownloading() {
        try {
            List<MyDownloadInfLocal> myDownloadInfLocals = myDownloadInfLocalDao.queryBuilder().where(MyDownloadInfLocalDao.Properties.Status.notEq(DownloadInfo.STATUS_COMPLETED)).list();
            return convertDownloadInfos(myDownloadInfLocals);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }


    @Override
    public List<DownloadInfo> findAllDownloaded() {
        try {
            List<MyDownloadInfLocal> myDownloadInfLocals = myDownloadInfLocalDao.queryBuilder().where(MyDownloadInfLocalDao.Properties.Status.eq(DownloadInfo.STATUS_COMPLETED)).list();
            return convertDownloadInfos(myDownloadInfLocals);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    @Override
    public DownloadInfo findDownloadedInfoById(long id) {
        try {
            return convertDownloadInfo(myDownloadInfLocalDao.load(id));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public DownloadInfo findDownloadedInfoBySourceId(int id) {
        return null;
    }

    @Override
    public void pauseAllDownloading() {
        try {
            List<MyDownloadInfLocal> list = myDownloadInfLocalDao.queryBuilder().where(MyDownloadInfLocalDao.Properties.Status.notEq(DownloadInfo.STATUS_COMPLETED)).list();
            for (int i = 0; i < list.size(); i++) {
                list.get(i).setStatus(DownloadInfo.STATUS_PAUSED);
            }
            myDownloadInfLocalDao.updateInTx(list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void createOrUpdate(DownloadInfo downloadInfo) {
        try {
            myDownloadInfLocalDao.insertOrReplace(convertDownloadInfo(downloadInfo));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void createOrUpdate(DownloadThreadInfo downloadThreadInfo) {
        try {
            myDownloadThreadInfoLocalDao.insertOrReplace(convertDownloadThreadInfo(downloadThreadInfo));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void delete(DownloadInfo downloadInfo) {
        try {
            myDownloadInfLocalDao.deleteByKey((long) downloadInfo.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void delete(DownloadThreadInfo download) {
        try {
            myDownloadThreadInfoLocalDao.deleteByKey((long) download.getDownloadInfoId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private List<DownloadInfo> convertDownloadInfos(List<MyDownloadInfLocal> infos) {
        List<DownloadInfo> downloadInfos = new ArrayList<>();
        for (MyDownloadInfLocal downloadInfLocal : infos) {
            downloadInfos.add(convertDownloadInfo(downloadInfLocal));
        }
        return downloadInfos;
    }


    private DownloadInfo convertDownloadInfo(MyDownloadInfLocal downloadInfLocal) {
        if (downloadInfLocal == null) {
            return null;
        }
        DownloadInfo downloadInfo = new DownloadInfo();
        downloadInfo.setCreateAt(downloadInfLocal.getCreateAt());
        downloadInfo.setUri(downloadInfLocal.getUri());
        downloadInfo.setPath(downloadInfLocal.getPath());
        downloadInfo.setSize(downloadInfLocal.getSize());
        downloadInfo.setProgress(downloadInfLocal.getProgress());
        downloadInfo.setStatus(downloadInfLocal.getStatus());
        downloadInfo.setSupportRanges(downloadInfLocal.getSupportRanges());
        downloadInfo.setDownloadThreadInfos(
                converDownloadThreadInfos1(downloadInfLocal.getDownloadThreadInfos()));
        return downloadInfo;
    }

    private List<DownloadThreadInfo> converDownloadThreadInfos1(
            List<MyDownloadThreadInfoLocal> downloadThreadInfosLocal) {
        List<DownloadThreadInfo> downloadThreadInfos = new ArrayList<>();
        if (downloadThreadInfosLocal != null) {
            for (MyDownloadThreadInfoLocal d : downloadThreadInfosLocal) {
                downloadThreadInfos.add(convertDownloadThreadInfo(d));
            }
        }

        return downloadThreadInfos;
    }

    private List<MyDownloadThreadInfoLocal> convertDownloadThreadInfos(
            List<DownloadThreadInfo> downloadThreadInfos) {
        if (downloadThreadInfos == null) {
            return null;
        }
        List<MyDownloadThreadInfoLocal> downloadThreadInfosLocal = new ArrayList<>();
        for (DownloadThreadInfo d : downloadThreadInfos
                ) {
            downloadThreadInfosLocal.add(convertDownloadThreadInfo(d));
        }
        return downloadThreadInfosLocal;
    }


    private DownloadThreadInfo convertDownloadThreadInfo(MyDownloadThreadInfoLocal d) {
        DownloadThreadInfo downloadThreadInfo = new DownloadThreadInfo();
        downloadThreadInfo.setId((int) d.getId());
        downloadThreadInfo.setThreadId(d.getThreadId());
        downloadThreadInfo.setDownloadInfoId(d.getDownloadInfoId());
        downloadThreadInfo.setUri(d.getUri());
        downloadThreadInfo.setStart(d.getStart());
        downloadThreadInfo.setEnd(d.getEnd());
        downloadThreadInfo.setProgress(d.getProgress());
        return downloadThreadInfo;
    }

    private MyDownloadThreadInfoLocal convertDownloadThreadInfo(DownloadThreadInfo d) {
        MyDownloadThreadInfoLocal downloadThreadInfo = new MyDownloadThreadInfoLocal();
        downloadThreadInfo.setId(d.getId());
        downloadThreadInfo.setThreadId(d.getThreadId());
        downloadThreadInfo.setDownloadInfoId(d.getDownloadInfoId());
        downloadThreadInfo.setUri(d.getUri());
        downloadThreadInfo.setStart(d.getStart());
        downloadThreadInfo.setEnd(d.getEnd());
        downloadThreadInfo.setProgress(d.getProgress());
        return downloadThreadInfo;
    }

    private MyDownloadInfLocal convertDownloadInfo(DownloadInfo downloadInfo) {
        MyDownloadInfLocal downloadInfLocal = new MyDownloadInfLocal();
        downloadInfLocal.setId(downloadInfo.getId());
        downloadInfLocal.setCreateAt(downloadInfo.getCreateAt());
        downloadInfLocal.setUri(downloadInfo.getUri());
        downloadInfLocal.setPath(downloadInfo.getPath());
        downloadInfLocal.setSize(downloadInfo.getSize());
        downloadInfLocal.setProgress(downloadInfo.getProgress());
        downloadInfLocal.setStatus(downloadInfo.getStatus());
        downloadInfLocal.setSupportRanges(downloadInfo.getSupportRanges());
        downloadInfLocal
                .setDownloadThreadInfos(convertDownloadThreadInfos(downloadInfo.getDownloadThreadInfos()));
        return downloadInfLocal;
    }
}
